--[[ 武装飞鸟2脚本脚本,从s1945ii改装过来,坐标表示相当简单直接!
  
  貌似几乎不费劲就搞定了,数据简洁又跟s1945ii很相似.
  增加了一些近日才加入的防错机制
  
  By setycyas @2025-02-08
]]

-- 这里设定基本参数
local GAME = {
  -- 游戏名,防重加载用
  NAME = "gunbird2_autoboot",
  -- 防错,一旦运行出错立即设定为true,在main()函数中使用,可避免绑定每帧运行后不断出错
  ERROR_FLAG = false,
  -- 分辨率
  X_RESOLUTION = 224,
  Y_RESOLUTION = 320,
  -- 横坐标只需要低位,纵坐标用read_u16读取,需要从高位读起
  X_ADDR = 0x06055011,
  Y_ADDR = 0x06055014,
  -- 火力与蓄力地址
  POW_ADDR = 0x0605505b,
  CHARGE_ADDR = 0x06055074,
  -- 显示方块的半长半高,单位为MAME的屏幕比例
  BOX_HALF_WIDTH = 0.0065,
  BOX_HALF_HEIGHT = 0.006,
  -- 为看得更清楚,再画两个较大的长方体
  XBOX_HALF_WIDTH = 0.032,
  XBOX_HALF_HEIGHT = 0.0065,
  YBOX_HALF_WIDTH = 0.0065,
  YBOX_HALF_HEIGHT = 0.035,
  YBOX_OFFSET = 0.005,
  -- 像素平移
  X_OFFSET = 0,
  Y_OFFSET = 0,
  -- 蓄力情况不同的颜色
  CHARGE_COLOR0 = 0xDDaaaaaa,
  CHARGE_COLOR1 = 0xDD0000ff,
  CHARGE_COLOR2 = 0xDDffd700,
  -- 蓄力等级需要的数值,貌似不同人物不同,这里用了隐藏人物(密码51024,随机人物按"下")的数据
  CHARGE_LV1 = 0x288,
  CHARGE_LV2 = 0x1700,
  -- mame api用的对象
  mem = manager.machine.devices[':maincpu'].spaces['program'],
  container = manager.machine.screens[":screen"].container,
  ui_container = manager.machine.render.ui_container,
}

-- 刷新设备,成功获取设备返回true,否返回false
function GAME.refreshDevices()
  GAME.mem = manager.machine.devices[':maincpu'].spaces['program']
  GAME.container = manager.machine.screens[":screen"].container
  GAME.ui_container = manager.machine.render.ui_container
  
  if (GAME.mem and GAME.container and GAME.ui_container) then
    return true
  else
    return false
  end
end

-- 坐标变换函数,从得到的坐标变为屏幕显示位置(是个比例),返回0.0-1.0的浮点数,
-- 后期游戏可能很复杂,需要根据游戏的情况手动操作变化
function GAME.getX()
  local xlow
  xlow =  1.0*GAME.mem:read_u8(GAME.X_ADDR)
  return (xlow+GAME.X_OFFSET)/GAME.X_RESOLUTION
end
function GAME.getY()
  local yword -- 2字节所以叫word
  yword =  1.0*GAME.mem:read_u16(GAME.Y_ADDR)
  return (yword+GAME.Y_OFFSET)/GAME.Y_RESOLUTION
end

-- 数据显示
function GAME.showInfo(GAMEList ,position, color)
  
  for index, value in ipairs(GAMEList) do
    GAME.ui_container:draw_text(position, 0.05*index, value, color)
  end
  
end

-- 显示监视的数据
function GAME.check()
  local power, charge
  power = GAME.mem:read_u8(GAME.POW_ADDR)
  charge = GAME.mem:read_u16(GAME.CHARGE_ADDR)
  GAME.container:draw_text(0, 0, "P="..power, 0xFF005500, 0xFFcccccc)
  GAME.ui_container:draw_text(0.02, 0.07, string.format("%x", charge))
  end

-- 显示辅助线
function GAME.showAssist()
  GAME.ui_container:draw_box(0.495, 1.0, 0.505, 0.97, 0xDDdd00dd, 0xDDdd00dd)
end

-- 显示方块,x,y是浮点数坐标
function GAME.showSqua(x, y)
  local container, charge, chargeColor
  container = GAME.container
  charge = GAME.mem:read_u16(GAME.CHARGE_ADDR)
  -- 根据蓄力情况获取颜色
  if (charge < GAME.CHARGE_LV1) then
    chargeColor = GAME.CHARGE_COLOR0
  elseif (charge < GAME.CHARGE_LV2) then
    chargeColor = GAME.CHARGE_COLOR1
  else
    chargeColor = GAME.CHARGE_COLOR2
  end
    
  if (x > 0.0) and (y > 0.0) then
    -- 十字框
    container:draw_box(
      y-GAME.XBOX_HALF_HEIGHT,
      x-GAME.XBOX_HALF_WIDTH,
      y+GAME.XBOX_HALF_HEIGHT,
      x+GAME.XBOX_HALF_WIDTH,
      0xFFFF00FF, chargeColor
    )
  
    container:draw_box(
      y-GAME.YBOX_HALF_HEIGHT-GAME.YBOX_OFFSET,
      x-GAME.YBOX_HALF_WIDTH,
      y+GAME.YBOX_HALF_HEIGHT-GAME.YBOX_OFFSET,
      x+GAME.YBOX_HALF_WIDTH,
      0xFFFF00FF, chargeColor
    )
    -- 中心
    container:draw_box(
      y-GAME.BOX_HALF_HEIGHT,
      x-GAME.BOX_HALF_WIDTH,
      y+GAME.BOX_HALF_HEIGHT,
      x+GAME.BOX_HALF_WIDTH,
      0xFFFF0000, 0xFFFF0000
    )
  end
  
end

-- 主函数,绑定后每一帧执行一次该函数
function GAME.main()
  local x, y
  
  -- 刷新设备,并判断当前帧能否操作
  if (not GAME.refreshDevices()) then
    return
  end
  if GAME.ERROR_FLAG then
    return
  end

  x = GAME.getX()
  y = GAME.getY()
  
  -- 显示监视数据
  --GAME.showInfo({power, charge}, 0.05, 0xFF00ff00)
  -- 辅助线
  GAME.showAssist()
  -- 数据监视
  GAME.check()
  -- 显示角色中心方块
  GAME.showSqua(x, y)

end
-- 调试时绑定此函数,确认无错误后可绑定main提高运行效率
function GAME.debug()
  local success, err = pcall(GAME.main)
  if not success then
    print("捕获到错误：", err)
    GAME.ERROR_FLAG = true
  end
end

-- [[运行]]
-- 避免重复加载
if ((_G.game) and (_G.game.NAME) and (_G.game.NAME == GAME.NAME)) then
  print("script already loaded!")
  return _G.game
else
  print("script load: "..GAME.NAME)
end

-- 绑定每一帧执行的函数
emu.register_frame_done(GAME.main, "frame")
--emu.register_frame_done(GAME.debug, "frame")
-- 导出到全局变量
_G.game = GAME

return GAME